#include "Int_Key.h"

/**
 * @brief Key1初始化
 */
void Int_Key_Key1Init(void)
{
    // 1. 时钟使能 ----------------------------
    // 1.1 对GPIOF时钟使能
    RCC->APB2ENR |= RCC_APB2ENR_IOPFEN;
    // 1.2 对AFIO时钟使能
    RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;

    // 2. GPIO引脚模式设置 ---------------------
    // 2.1 设置 PF7 为上下拉输入：MODE=00; CNF=10
    GPIOF->CRL &= ~GPIO_CRL_MODE7;
    GPIOF->CRL |= GPIO_CRL_CNF7_1;
    GPIOF->CRL &= ~GPIO_CRL_CNF7_0;
    // 2.2 通过设置ODR明确是下拉输入
    GPIOF->ODR &= ~GPIO_ODR_ODR7;

    // 3. AFIO和EXTI 设置 -----------------------
    // 3.1 EXTI7 使用 PF7, 使用 AFIO_EXTICR2 寄存器
    AFIO->EXTICR[1] &= ~AFIO_EXTICR2_EXTI7; // 将EXTI9对应的4个bit全部置0
    AFIO->EXTICR[1] |= AFIO_EXTICR2_EXTI7_PF;
    // 3.2 EXTI 设置上升沿触发
    EXTI->RTSR |= EXTI_RTSR_TR7;
    // 3.3 EXTI 设置下降沿不触发（默认值）
    EXTI->FTSR &= ~EXTI_FTSR_TR7;
    // 3.4 取消EXTI7的屏蔽
    EXTI->IMR |= EXTI_IMR_MR7;

    // 4. NVIC 设置
    // 4.1 设置抢占优先级为4位, 将 SCB_AIRCR 寄存器中的 PRIGROUP 控制器设置为 011
    NVIC_SetPriorityGrouping(3);
    // 4.2 使能中断向量 EXTI9_5
    NVIC_EnableIRQ(EXTI9_5_IRQn);
    // 4.3 设置 EXTI9_5 中断向量的优先级
    NVIC_SetPriority(EXTI9_5_IRQn, 5);
}

/**
 * @brief Key2初始化
 */
void Int_Key_Key2Init(void)
{
    // 1. 时钟使能 ----------------------------
    // 1.1 对GPIOF时钟使能
    RCC->APB2ENR |= RCC_APB2ENR_IOPFEN;
    // 1.2 对AFIO时钟使能
    RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;

    // 2. GPIO引脚模式设置 ---------------------
    // 2.1 设置 PF7 为上下拉输入：MODE=00; CNF=10
    GPIOF->CRH &= ~GPIO_CRH_MODE8;
    GPIOF->CRH |= GPIO_CRH_CNF8_1;
    GPIOF->CRH &= ~GPIO_CRH_CNF8_0;
    // 2.2 通过设置ODR明确是下拉输入
    GPIOF->ODR &= ~GPIO_ODR_ODR8;

    // 3. AFIO和EXTI 设置 -----------------------
    // 3.1 EXTI9 使用 PF8, 使用 AFIO_EXTICR3 寄存器
    AFIO->EXTICR[2] &= ~AFIO_EXTICR3_EXTI8; // 将EXTI9对应的4个bit全部置0
    AFIO->EXTICR[2] |= AFIO_EXTICR3_EXTI8_PF;
    // 3.2 EXTI 设置上升沿触发
    EXTI->RTSR |= EXTI_RTSR_TR8;
    // 3.3 EXTI 设置下降沿不触发（默认值）
    EXTI->FTSR &= ~EXTI_FTSR_TR8;
    // 3.4 取消EXTI7的屏蔽
    EXTI->IMR |= EXTI_IMR_MR8;

    // 4. NVIC 设置
    // 4.1 设置抢占优先级为4位, 将 SCB_AIRCR 寄存器中的 PRIGROUP 控制器设置为 011
    NVIC_SetPriorityGrouping(3);
    // 4.2 使能中断向量 EXTI9_5
    NVIC_EnableIRQ(EXTI9_5_IRQn);
    // 4.3 设置 EXTI9_5 中断向量的优先级
    NVIC_SetPriority(EXTI9_5_IRQn, 5);
}

/**
 * @brief Key3初始化
 */
void Int_Key_Key3Init(void)
{
    // 1. 时钟使能 ----------------------------
    // 1.1 对GPIOF时钟使能
    RCC->APB2ENR |= RCC_APB2ENR_IOPFEN;
    // 1.2 对AFIO时钟使能
    RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;

    // 2. GPIO引脚模式设置 ---------------------
    // 2.1 设置 PF9 为上下拉输入：MODE=00; CNF=10
    GPIOF->CRH &= ~GPIO_CRH_MODE9;
    GPIOF->CRH |= GPIO_CRH_CNF9_1;
    GPIOF->CRH &= ~GPIO_CRH_CNF9_0;
    // 2.2 通过设置ODR明确是下拉输入
    GPIOF->ODR &= ~GPIO_ODR_ODR9;

    // 3. AFIO和EXTI 设置 -----------------------
    // 3.1 EXTI9 使用 PF9, 使用 AFIO_EXTICR3 寄存器
    AFIO->EXTICR[2] &= ~AFIO_EXTICR3_EXTI9; // 将EXTI9对应的4个bit全部置0
    AFIO->EXTICR[2] |= AFIO_EXTICR3_EXTI9_PF;
    // 3.2 EXTI 设置上升沿触发
    EXTI->RTSR |= EXTI_RTSR_TR9;
    // 3.3 EXTI 设置下降沿不触发（默认值）
    EXTI->FTSR &= ~EXTI_FTSR_TR9;
    // 3.4 取消EXTI7的屏蔽
    EXTI->IMR |= EXTI_IMR_MR9;

    // 4. NVIC 设置
    // 4.1 设置抢占优先级为4位, 将 SCB_AIRCR 寄存器中的 PRIGROUP 控制器设置为 011
    NVIC_SetPriorityGrouping(3);
    // 4.2 使能中断向量 EXTI9_5
    NVIC_EnableIRQ(EXTI9_5_IRQn);
    // 4.3 设置 EXTI9_5 中断向量的优先级
    NVIC_SetPriority(EXTI9_5_IRQn, 5);
}

/**
 * @brief Key4初始化
 */
void Int_Key_Key4Init(void)
{
    // 1. 时钟使能 ----------------------------
    // 1.1 对GPIOF时钟使能
    RCC->APB2ENR |= RCC_APB2ENR_IOPFEN;
    // 1.2 对AFIO时钟使能
    RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;

    // 2. GPIO引脚模式设置 ---------------------
    // 2.1 设置 PF10 为上下拉输入：MODE=00; CNF=10
    GPIOF->CRH &= ~GPIO_CRH_MODE10;
    GPIOF->CRH |= GPIO_CRH_CNF10_1;
    GPIOF->CRH &= ~GPIO_CRH_CNF10_0;
    // 2.2 通过设置ODR明确是上拉输入
    GPIOF->ODR |= GPIO_ODR_ODR10;

    // 3. AFIO和EXTI 设置 -----------------------
    // 3.1 EXTI9 使用 PF10, 使用 AFIO_EXTICR3 寄存器
    AFIO->EXTICR[2] &= ~AFIO_EXTICR3_EXTI10; // 将EXTI9对应的4个bit全部置0
    AFIO->EXTICR[2] |= AFIO_EXTICR3_EXTI10_PF;
    // 3.2 EXTI 设置上升沿不触发
    EXTI->RTSR &= ~EXTI_RTSR_TR10;
    // 3.3 EXTI 设置下降沿触发
    EXTI->FTSR |= EXTI_FTSR_TR10;
    // 3.4 取消EXTI10的屏蔽
    EXTI->IMR |= EXTI_IMR_MR10;

    // 4. NVIC 设置
    // 4.1 设置抢占优先级为4位, 将 SCB_AIRCR 寄存器中的 PRIGROUP 控制器设置为 011
    NVIC_SetPriorityGrouping(3);
    // 4.2 使能中断向量 EXTI15_10
    NVIC_EnableIRQ(EXTI15_10_IRQn);
    // 4.3 设置 EXTI15_10 中断向量的优先级
    NVIC_SetPriority(EXTI15_10_IRQn, 5);
}

/**
 * @brief Key5初始化
 */
void Int_Key_Key5Init(void)
{
    // 1. 时钟使能 ----------------------------
    // 1.1 对GPIOF时钟使能
    RCC->APB2ENR |= RCC_APB2ENR_IOPFEN;
    // 1.2 对AFIO时钟使能
    RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;

    // 2. GPIO引脚模式设置 ---------------------
    // 2.1 设置 PF11 为上下拉输入：MODE=00; CNF=10
    GPIOF->CRH &= ~GPIO_CRH_MODE11;
    GPIOF->CRH |= GPIO_CRH_CNF11_1;
    GPIOF->CRH &= ~GPIO_CRH_CNF11_0;
    // 2.2 通过设置ODR明确是上拉输入
    GPIOF->ODR |= GPIO_ODR_ODR11;

    // 3. AFIO和EXTI 设置 -----------------------
    // 3.1 EXTI9 使用 PF10, 使用 AFIO_EXTICR3 寄存器
    AFIO->EXTICR[2] &= ~AFIO_EXTICR3_EXTI11; // 将EXTI9对应的4个bit全部置0
    AFIO->EXTICR[2] |= AFIO_EXTICR3_EXTI11_PF;
    // 3.2 EXTI 设置上升沿不触发
    EXTI->RTSR &= ~EXTI_RTSR_TR11;
    // 3.3 EXTI 设置下降沿触发
    EXTI->FTSR |= EXTI_FTSR_TR11;
    // 3.4 取消EXTI11的屏蔽
    EXTI->IMR |= EXTI_IMR_MR11;

    // 4. NVIC 设置
    // 4.1 设置抢占优先级为4位, 将 SCB_AIRCR 寄存器中的 PRIGROUP 控制器设置为 011
    NVIC_SetPriorityGrouping(3);
    // 4.2 使能中断向量 EXTI15_10
    NVIC_EnableIRQ(EXTI15_10_IRQn);
    // 4.3 设置 EXTI15_10 中断向量的优先级
    NVIC_SetPriority(EXTI15_10_IRQn, 5);
}

/***************************************************************************************/
// 定义弱函数，当Key1被按下后会被调用
__weak void Int_Key_Key1Callback(void)
{
}

// 定义弱函数，当Key2被按下后会被调用
__weak void Int_Key_Key2Callback(void)
{
}

// 定义弱函数，当Key3被按下后会被调用
__weak void Int_Key_Key3Callback(void)
{
}

// 定义弱函数，当Key4被按下后会被调用
__weak void Int_Key_Key4Callback(void)
{
}

// 定义弱函数，当Key5被按下后会被调用
__weak void Int_Key_Key5Callback(void)
{
}

/***************************************************************************************/
// 定义中断向量 EXTI9_5 的中断服务函数
void EXTI9_5_IRQHandler()
{

    // 根据标志位判断具体哪个EXTI中断
    // 如果EXTI7
    if (EXTI->PR & EXTI_PR_PR7)
    {
        // 清除标志位，写入1即可清除
        EXTI->PR |= EXTI_PR_PR7;

        // 延时10ms, 进行消抖处理
        Delay_ms(10);

        // 再次判断 PF7 引脚是否是高电平
        if (GPIOF->IDR & GPIO_IDR_IDR7)
        {
            // 处理按键触发后的逻辑, 调用弱函数
            Int_Key_Key1Callback();
        }
    }

    // 如果EXTI8
    if (EXTI->PR & EXTI_PR_PR8)
    {
        // 清除标志位，写入1即可清除
        EXTI->PR |= EXTI_PR_PR8;

        // 延时10ms, 进行消抖处理
        Delay_ms(10);

        // 再次判断 PF8 引脚是否是高电平
        if (GPIOF->IDR & GPIO_IDR_IDR8)
        {
            // 处理按键触发后的逻辑, 调用弱函数
            Int_Key_Key2Callback();
        }
    }

    // 如果EXTI9
    if (EXTI->PR & EXTI_PR_PR9)
    {
        // 清除标志位，写入1即可清除
        EXTI->PR |= EXTI_PR_PR9;

        // 延时10ms, 进行消抖处理
        Delay_ms(10);

        // 再次判断 PF9 引脚是否是高电平
        if (GPIOF->IDR & GPIO_IDR_IDR9)
        {
            // 处理按键触发后的逻辑, 调用弱函数
            Int_Key_Key3Callback();
        }
    }
}

// 定义中断向量 EXTI15_10 的中断服务函数
void EXTI15_10_IRQHandler(void)
{
 
    // 如果EXTI10
    if (EXTI->PR & EXTI_PR_PR10)
    {
        // 清除标志位，写入1即可清除
        EXTI->PR |= EXTI_PR_PR10;

        // 延时10ms, 进行消抖处理
        Delay_ms(10);

        // 再次判断 PF10 引脚是否是低电平
        if ((GPIOF->IDR & GPIO_IDR_IDR10) == 0)
        {
            // 处理按键触发后的逻辑, 调用弱函数
            Int_Key_Key4Callback();
        }
    }

    // 如果EXTI11
    if (EXTI->PR & EXTI_PR_PR11)
    {
        // 清除标志位，写入1即可清除
        EXTI->PR |= EXTI_PR_PR11;

        // 延时10ms, 进行消抖处理
        Delay_ms(10);

        // 再次判断 PF11 引脚是否是低电平
        if ((GPIOF->IDR & GPIO_IDR_IDR11) == 0)
        {
            // 处理按键触发后的逻辑, 调用弱函数
            Int_Key_Key5Callback();
        }
    }
}
